// RotateAndScaleStrategy.java
// by Alexandre Martins, 2013
// MAC 5857 - Prof. Leonidas

package example.ilm.model;

import ilm.framework.assignment.model.DomainAction;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.HashMap;

import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;

public class RotateAndScaleStrategy implements DragnDropStrategy
{
    private Polygon polygon;
    private Point2D initialOffset;
    private double initialAngle;
    private double unitLength;
    private double initialScale;

    public RotateAndScaleStrategy(Polygon polygon, int x, int y)
    {
        this.polygon = polygon;

        // rotation
        initialAngle = polygon.getAngle();
        initialOffset = new Point2D.Double(
            x - polygon.getPosition().getX(),
            y - polygon.getPosition().getY()
        );
        double mag = initialOffset.distance(0, 0);
        if(mag < 1e-5) mag = 1e-5;
        initialOffset = new Point2D.Double( initialOffset.getX() / mag, initialOffset.getY() / mag );

        // scale
        initialScale = polygon.getScale();
        unitLength = (new Point2D.Double(x, y)).distance(polygon.getPosition());
        if(unitLength < 1)
            unitLength = 1;
    }

    public void drag(int x, int y)
    {
        // rotation
        Point2D currentOffset = new Point2D.Double(
            x - polygon.getPosition().getX(),
            y - polygon.getPosition().getY()
        );
        double mag = currentOffset.distance(0, 0);
        if(mag < 1e-5) mag = 1e-5;
        currentOffset = new Point2D.Double( currentOffset.getX() / mag, currentOffset.getY() / mag );
        double theta = Math.acos( initialOffset.getX() * currentOffset.getX() + initialOffset.getY() * currentOffset.getY() );
        double sign = ( initialOffset.getY() * currentOffset.getX() - initialOffset.getX() * currentOffset.getY() ) < 0 ? 1.0 : -1.0;
        polygon.setAngle(initialAngle + sign * theta);

        // scale
        Point2D delta = new Point2D.Double(
            x - polygon.getPosition().getX(),
            y - polygon.getPosition().getY()
        );
        double magnitude = delta.distance(0, 0);
        polygon.setScale(initialScale * magnitude / unitLength);
    }

    public void drop(HashMap theDomainActions)
    {
        RotateAndScalePolygon action = (RotateAndScalePolygon)theDomainActions.get("rotateAndScalePolygon");
        action.setPolygon(polygon);
        action.rotateAndScale(polygon.getAngle() - initialAngle, polygon.getScale() / initialScale);
        polygon.setAngle(initialAngle);
        polygon.setScale(initialScale);
        action.execute();
    }
    
    public GeometricElement getGeometricElement()
    {
    	return polygon;
    }
}
